﻿using Airthmetic;
using BaseTool;
using Kitware.VTK;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace StructuredLightSystemUI
{
    /// <summary>
    /// 点云显示页面
    /// </summary>
    public partial class ConPointCloudShow : UserControl
    {
        /// <summary> 3D显示 </summary>
        private RenderWindowControl renderWindowControl1 = new RenderWindowControl();
        /// <summary> 刷新显示锁 </summary>
        private readonly object lockRefreshPointCloud = new object();


        /// <summary> 点云路径 </summary>
        private List<string> plyPath = new List<string>();
        /// <summary> 点云图片路径 </summary>
        private List<string> plyImagePath = new List<string>();

        #region 构造、初始化
        /// <summary>
        /// 构造
        /// </summary>
        public ConPointCloudShow()
        {
            InitializeComponent();
        }

        //加载时
        private void ConPointCloudShow_Load(object sender, EventArgs e)
        {
            renderWindowControl1.Dock = DockStyle.Fill;
            this.splitContainer1.Panel2.Controls.Add(renderWindowControl1);
        }

        /// <summary> 打开用户控件 </summary>
        public void OpenControl()
        {
            RefreshReconstruct(false);
        }

        /// <summary> 关闭用户控件 </summary>
        public void CloseControl()
        {

        }
        #endregion

        /// <summary>
        /// 刷新点云数据
        /// </summary>
        private void RefreshReconstruct(bool isInvoke = true)
        {
            //点云数据
            if (isInvoke)
            {
                lb_DataShow.Invoke((MethodInvoker)delegate
                {
                    lb_DataShow.ClearSelected();
                    lb_DataShow.Items.Clear();

                    List<string> reName = new List<string>();
                    ImageTool.LoadReconstruct(out plyPath, out plyImagePath, out reName);

                    foreach (string name in reName)
                    {
                        lb_DataShow.Items.Add(name);
                    }
                });
            }
            else
            {
                lb_DataShow.ClearSelected();
                lb_DataShow.Items.Clear();

                List<string> reName = new List<string>();
                ImageTool.LoadReconstruct(out plyPath, out plyImagePath, out reName);

                foreach (string name in reName)
                {
                    lb_DataShow.Items.Add(name);
                }
            }
        }

        /// <summary>
        /// 显示原图
        /// </summary>
        /// <param name="points">点云数据</param>
        /// <param name="colorRGB">彩色数据</param>
        public void ShowImage(vtkPoints points, vtkUnsignedCharArray colorRGB)
        {
            try
            {
                lock (lockRefreshPointCloud)
                {
                    //显示彩色点云
                    ShowColorfulPointCloud(renderWindowControl1, points, colorRGB);
                    this.Text = $"点云显示（Point：{points.GetNumberOfPoints()}）";
                }
            }
            catch (Exception ex)
            {
                Log.SaveError(ex, $"点云显示异常，{ex.Message}");
            }
        }

        #region 杂项
        //切换侧边栏显示/隐藏
        private void 侧边栏隐藏ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ChangeCollapsed(!splitContainer1.Panel1Collapsed);
        }
        /// <summary>
        /// 设置侧边栏显示/隐藏
        /// </summary>
        private void ChangeCollapsed(bool Collapsed)
        {
            splitContainer1.Panel1Collapsed = Collapsed;
            侧边栏隐藏ToolStripMenuItem.Text = Collapsed ? $"侧边栏显示" : "侧边栏隐藏";
        }
        #endregion

        #region 侧边栏事件

        //兔子
        private void b_rabbit_Click(object sender, EventArgs e)
        {
            try
            {
                RabbitTool rabbit = new RabbitTool();
                vtkPoints pointsVtk;
                vtkUnsignedCharArray colorRGB;
                if (!TransitionType(rabbit.SavePCD(), out pointsVtk, out colorRGB))
                {
                    Log.SaveLog($"显示兔子失败，转换数据失败", LogType.Run, Color.Red);
                    return;
                }
                ShowImage(pointsVtk, colorRGB);
            }
            catch (Exception ex)
            {
                Log.SaveError(ex, $"显示兔子异常，{ex.Message}");
            }
        }
        #endregion

        #region 重要功能
        /// <summary>
        /// 转换数据
        /// </summary>
        /// <param name="pointsXyz"></param>
        /// <param name="pointsVtk"></param>
        /// <param name="colorRGB"></param>
        /// <returns></returns>
        public bool TransitionType(Point_XYZ[] pointsXyz, out vtkPoints pointsVtk, out vtkUnsignedCharArray colorRGB)
        {
            try
            {
                //1初始化
                pointsVtk = new vtkPoints();
                colorRGB = vtkUnsignedCharArray.New();
                colorRGB.SetNumberOfComponents(3);

                //2转换数据
                for (int i = 0; i < pointsXyz.Length; i++)
                {
                    pointsVtk.InsertPoint(i, pointsXyz[i].X, pointsXyz[i].Y, pointsXyz[i].Z);
                    //colorRGB.InsertNextTuple3(pointsXyz[i].X % 256, pointsXyz[i].Y % 256, pointsXyz[i].X % 256);
                    colorRGB.InsertNextTuple3(255, 255, 255);
                }
                return true;
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
                pointsVtk = null;
                colorRGB = null;
                return false;
            }
        }

        /// <summary>
        /// 显示彩色点云
        /// </summary>
        /// <param name="control"></param>
        /// <param name="points"></param>
        /// <param name="colorRGB"></param>
        public void ShowColorfulPointCloud(
            RenderWindowControl control,
            vtkPoints points,
            vtkUnsignedCharArray colorRGB)
        {
            //清空点云
            vtkRenderer render = control.RenderWindow.GetRenderers().GetFirstRenderer();
            for (int i = 0; i < render.GetActors().GetNumberOfItems(); i++)
            {
                var item = render.GetActors().GetItemAsObject(i);
                render.RemoveActor((vtkActor)item);
                item.Dispose();
            }

            //初始化点云数据
            vtkPolyData polydata = vtkPolyData.New();
            //设置点云数据
            polydata.SetPoints(points);
            //设置点云的渲染标量
            polydata.GetPointData().SetScalars(colorRGB);

            //初始化顶点过滤器
            vtkVertexGlyphFilter glyphFilter = vtkVertexGlyphFilter.New();
            //设置顶点过滤器
            glyphFilter.SetInputConnection(polydata.GetProducerPort());

            //初始化多边形数据映射
            vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
            //设置管线连接
            mapper.SetInputConnection(glyphFilter.GetOutputPort());
            //开启颜色渲染
            mapper.ScalarVisibilityOn();
            //设置渲染范围
            mapper.SetScalarRange(0, 500);

            //初始化图形渲染对象
            vtkActor actor = vtkActor.New();
            //设置数据映射
            actor.SetMapper(mapper);

            //控件添加渲染对象
            render.AddActor(actor);
            render.SetViewport(0.0, 0.0, 1, 1);
            render.ResetCamera();
            control.Refresh();
        }
        #endregion
        //显示点云图像
        private void lb_DataShow_SelectedIndexChanged(object sender, EventArgs e)
        {
            int SelectedIndex = lb_DataShow.SelectedIndex;
            if (SelectedIndex == -1 ||
                SelectedIndex >= plyImagePath.Count ||
                string.IsNullOrWhiteSpace(plyImagePath[SelectedIndex]))
                return;

            if (!File.Exists(plyImagePath[SelectedIndex]))
                return;

            rtb_DataShow.Text = $"点云路径：(双击打开)\r\n{plyPath[SelectedIndex]}\r\n\r\n图像路径：\r\n{plyImagePath[SelectedIndex]}";
        }
        //打开点云图
        private void lb_DataShow_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            int SelectedIndex = this.lb_DataShow.IndexFromPoint(e.Location);
            if (SelectedIndex == -1 ||
                SelectedIndex >= plyPath.Count ||
                string.IsNullOrWhiteSpace(plyPath[SelectedIndex]))
                return;

            try
            {
                if (!File.Exists(plyPath[SelectedIndex]))
                {
                    rtb_DataShow.Text = $"点云不存在：\r\n{plyPath[SelectedIndex]}";
                    return;
                }

                //1 获取点云
                Point_RGB[] rgb = PointCloudForm.GetPlyData(plyPath[SelectedIndex]);
                if (rgb.Length == 0)
                    return;

                //2 转换数据
                vtkPoints pointsVtk;
                vtkUnsignedCharArray colorRGB;
                if (!PointCloudForm.TransitionType(rgb, out pointsVtk, out colorRGB))
                {
                    Log.SaveLog($"转换数据失败", LogType.Run, Color.Red);
                    return;
                }

                //3 显示点云
                ShowImage(pointsVtk, colorRGB);
            }
            catch (Exception ex)
            {
                Log.SaveError(ex, $"显示点云异常，{ex.Message}");
            }
        }
    }
}
